package com.base.pub.util;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

public class ObjectUtils {

	public static Set<String> stringArrayIntersect(Collection<String> a1,
			Collection<String> a2) {
		Set<String> intersectionSet = new HashSet<String>();
		intersectionSet.addAll(a1);
		boolean result = intersectionSet.retainAll(a2);
		if (!result) {
			return Collections.EMPTY_SET;
		}
		return Collections.unmodifiableSet(intersectionSet);
	}

	public static <T extends Throwable> T unknownStackTrace(T cause,
			Class<?> clazz, String method) {
		cause.setStackTrace(new StackTraceElement[] { new StackTraceElement(
				clazz.getName(), method, null, -1) });
		return cause;
	}

	public static String stackTraceToString(Throwable cause) {
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		PrintStream pout = new PrintStream(out);
		cause.printStackTrace(pout);
		pout.flush();
		try {
			return new String(out.toByteArray());
		} finally {
			try {
				out.close();
			} catch (IOException ignore) {
				// ignore as should never happen
			}
		}
	}

	public static Map<String, Object> objectToMap(Object obj)
			throws IntrospectionException, IllegalAccessException,
			IllegalArgumentException, InvocationTargetException {

		Map<String, Object> map = new HashMap<String, Object>();

		BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());
		PropertyDescriptor[] propertyDescriptors = beanInfo
				.getPropertyDescriptors();
		for (PropertyDescriptor property : propertyDescriptors) {
			String key = property.getName();
			if (key.compareToIgnoreCase("class") == 0) {
				continue;
			}
			Method getter = property.getReadMethod();
			Object value = getter != null ? getter.invoke(obj) : null;
			map.put(key, value);
		}

		return map;
	}

	public static Object mapToObject(Map<String, Object> map, Class<?> beanClass)
			throws IntrospectionException, IllegalAccessException,
			IllegalArgumentException, InvocationTargetException,
			InstantiationException {

		Object obj = beanClass.newInstance();

		BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());
		PropertyDescriptor[] propertyDescriptors = beanInfo
				.getPropertyDescriptors();
		for (PropertyDescriptor property : propertyDescriptors) {
			Method setter = property.getWriteMethod();
			if (setter != null) {
				setter.invoke(obj, map.get(property.getName()));
			}
		}

		return obj;
	}
}
